home *** CD-ROM | disk | FTP | other *** search
- /* GNUPLOT -- mif.trm */
- /*
- * Copyright (C) 1992, 1993
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the modified code. Modifications are to be distributed
- * as patches to released version.
- *
- * This software is provided "as is" without express or implied warranty.
- *
- * This file is included by ../term.c.
- *
- * This terminal driver was developed for
- * gnuplot for unix version 3.0 (patchlevel 1)
- * gnuplot for unix version 3.2 (patchlevel 2)
- *
- * This terminal driver supports:
- * Frame Maker MIF format version 3.00
- *
- * Options for this terminal driver (set terminal mif [options]):
- * colour / Draw primitives with line types >= 0 in colour (sep. 2-7)
- * monochrome Draw primitives in black (sep. 0)
- *
- * polyline / Draw lines as continous curves
- * vectors Draw lines as collections of vectors
- *
- * help / ? Print short usage description on stderr
- *
- * Properties for this terminal driver:
- * -Gnuplot size of worksheet: MIF_XMAX * MIF_YMAX
- * -Unit in MIF output: cm
- * -Plot primitives with the same pen will
- * be grouped in the same MIF group.
- * -Plot primitives with line types >= 0
- * will as default be drawn in colour.
- * -Lines are plotted as collections of
- * vectors, or as continous lines (default)
- * -Plot primitives in a plot will be in a
- * Frame in MIF. Several plot Frames will
- * be collected in one large Frame.
- * -Point size of MIF output characters: MIF_PSIZE
- * -Used font for MIF output characters: Times
- * -Supports vertical text
- *
- * AUTHORS:
- * Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
- *
- * COMMENTS:
- * Send comments and/or suggestions to olof@fysik4.kth.se
- *
- * CHANGES:
- * Changed order of routine declarations. olof@fysik4.kth.se
- * Changed mechanism for pen pattern selection. kssingvo@immd4.informatik.uni-erlangen.de
- * Support for vertical text. kssingvo@immd4.informatik.uni-erlangen.de
- * Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
- *
- */
- #if !defined(cfree)
- #define cfree free
- #endif
-
- /** Coordinates **/
- #define GNP_TO_MIF(P) (((float) (P)) / 1000.0) /* Converts gnuplot units to MIF units */
- #define MIF_XMAX 15000 /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
- #define MIF_YMAX 10000 /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
-
- #define MIF_XLAST (MIF_XMAX - 1)
- #define MIF_YLAST (MIF_YMAX - 1)
-
- static struct mif_line { /* Line point structure specification */
- float fpos_x; /* Line point X coordinate */
- float fpos_y; /* Y coordinate */
- struct mif_line *next; /* Pointer to next line point */
- struct mif_line *prev; /* Pointer to previous line point */
- } mif_line = { /* Current position structure. Adjust for orign. Local for this file. */
- GNP_TO_MIF(0),
- GNP_TO_MIF(MIF_YLAST),
- &mif_line,
- &mif_line
- };
-
- /** Characters **/
- #define MIF_PSIZE 9 /* Point size of used characters */
-
- #define MIF_VCHAR (MIF_YMAX/31) /* Distance between rows (a guess) */
- #define MIF_HCHAR (MIF_XMAX/95) /* Distance between characters (a guess) */
-
- /** Scale marks **/
- #define MIF_VTIC (MIF_YMAX/150) /* Size of scale mark (vert) */
- #define MIF_HTIC (MIF_XMAX/225) /* Size of scale mark (hor) */
-
- /** Drawing properties **/
- static char mif_justify[64]; /* How to justify the used text */
- static char mif_pen[64], mif_pen_width[64], mif_separation[64]; /* How to plot */
-
- #define MIF_TEXT_HOR 0
- #define MIF_TEXT_VER 1
- static int mif_text_ang = MIF_TEXT_HOR; /* Rotation angle of text */
-
- #define MIF_NPENS 16 /* Number of MIF pen types */
- static int mif_pentype = 0; /* Pen type to use. Also used to create groups for graphics */
- #define MIF_PEN_TO_GROUP(P) ( 1 + (P) ) /* Map pen type to group number. Must be >= 1 */
-
- static int mif_pattern_table[MIF_NPENS] = { /* Table, which pattern should be used for drawing */
- 0, /* border */
- 1, /* not used */
- 2, 3, 4, 8, 12, 13, /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
- 5, /* grid */
- 9, 10, 11, 12, 13, 14, 15 /* not used */
- };
-
- /** MIF groups administration **/
- #define MIF_NGROUP_ID 20
- static struct mif_group_id {
- int group_existance;
- #define MIF_GROUP_EXISTS 1 /* This group id should generate a MIF group */
- #define MIF_GROUP_NOT_EXISTS 0 /* This group id should not generate a MIF group */
-
- int group_id;
- #define MIF_INVALID_GROUP_ID 0 /* An invalid MIF group ID */
-
- } mif_group_id[MIF_NGROUP_ID]; /* List of used group ID:s and corresponding MIF groups existance */
-
- /** Semaphores **/
- static int mif_initialized = 0; /* != 0 when output is active */
- static int mif_in_frame = 0; /* != 0 when inside a plot frame */
- static int mif_frameno = -1; /* Current frame number */
- static int mif_colour = TRUE; /* == TRUE when colour should be used */
- static int mif_polyline = TRUE; /* == TRUE when lines are drawn as continous curves */
-
- /** Declaration of routine/s for internal use **/
- static int insert_mif_line(), proc_group_id();
-
- /** Routine/s **/
-
- /* Called when this terminal type is set in order to parse options */
- MIF_options()
- {
- extern char term_options[]; /* Declared in ../setshow.c */
-
- if (!END_OF_COMMAND) {
- /* Colour options */
- if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) { /* Compare up to $ */
- mif_colour = FALSE;
- c_token++;
- }
- if (!END_OF_COMMAND && almost_equals(c_token, "c$olour")) { /* Compare up to $ */
- mif_colour = TRUE;
- c_token++;
- }
-
- /* Curve options */
- if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) { /* Compare up to $ */
- mif_polyline = FALSE;
- c_token++;
- }
- if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) { /* Compare up to $ */
- mif_polyline = TRUE;
- c_token++;
- }
-
- /* Short help */
- if ( !END_OF_COMMAND &&
- (almost_equals(c_token, "h$elp") ||
- almost_equals(c_token, "?$")) ) { /* Compare up to $ */
- fprintf(stderr, "Usage: set terminal mif [options]\n");
- fprintf(stderr, "\toptions:\n");
- fprintf(stderr, "\t\tcolour / Draw primitives with line types >= 0 in colour (sep. 2-7)\n");
- fprintf(stderr, "\t\tmonochrome Draw primitives in black (sep. 0) \n");
- fprintf(stderr, "\n");
- fprintf(stderr, "\t\tpolyline / Draw lines as continous curves \n");
- fprintf(stderr, "\t\tvectors Draw lines as collections of vectors \n");
- fprintf(stderr, "\n");
- fprintf(stderr, "\t\thelp / ? Print short usage description on stderr \n");
-
- c_token++;
- }
- }
-
- sprintf(term_options, "%s %s", (mif_colour == TRUE)? "colour": "monochrome",
- (mif_polyline == TRUE)? "polyline": "vectors");
- }
-
- /* Deallocate the used line structure elements */
- static int free_mif_line()
- {
- struct mif_line *tline;
-
- while (mif_line.prev != &mif_line) {
- /* Unlink */
- tline = mif_line.prev;
- mif_line.prev = mif_line.prev->prev;
- mif_line.prev->next = &mif_line;
-
- /* Deallocate */
- free(tline);
- }
-
- /* Make sure that the list will be empty */
- mif_line.prev = &mif_line;
- mif_line.next = &mif_line;
- }
-
- /* Draw the pending line. Change current position. */
- static int put_mif_line()
- {
- int np, i;
- struct mif_line *tline;
-
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Count the number of available points */
- for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++)
- ;
-
- /* Draw line (at least two points) */
- if (np >= 2) {
- /* Line preamble */
- fprintf(outfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
- MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
-
- /* Draw the line elements */
- fprintf(outfile, "\t\t<NumPoints %d> ", np);
- for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
- if (i%4 == 0)
- fprintf(outfile, "\n\t\t");
- fprintf(outfile, "<Point %.3f %.3f> ", tline->fpos_x, tline->fpos_y);
- }
-
- /* Line post amble */
- fprintf(outfile, "\n\t>\n");
-
- /* Register the used group ID */
- proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
-
- /* Avoid to redraw this. The MIF system should remember it. */
- mif_pen[0] = '\0';
- mif_pen_width[0] = '\0';
- mif_separation[0] = '\0';
-
- /* Move current position to end of line */
- mif_line.fpos_x = mif_line.prev->fpos_x;
- mif_line.fpos_y = mif_line.prev->fpos_y;
-
- /* Restore the line */
- free_mif_line();
- }
-
- } /* Line processed */
- }
-
- /* Set up a MIF output file */
- MIF_init()
- {
- int i;
-
- extern char version[]; /* Declared in ../version.c */
- extern char patchlevel[];
-
- /* Process if not inside a MIF file and Frame */
- if (mif_initialized == 0 && mif_in_frame == 0) {
- /* Tell this terminal driver that the output is initialized and no current frames are processed */
- mif_initialized = 1;
- mif_in_frame = 0;
-
- /* Reset internal position */
- free_mif_line();
- mif_line.fpos_x = GNP_TO_MIF(0);
- mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
-
- /* Reset drawing properties strings */
- mif_pen[0] = '\0';
- mif_pen_width[0] = '\0';
- mif_separation[0] = '\0';
- sprintf(mif_justify, " <TLAlignment Left> ");
-
- /* Reset group ID generator */
- for (i = 0; i < MIF_NGROUP_ID; i++) {
- mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
- mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
- }
-
- /* Identify ourselves */
- fprintf(outfile, "<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n", version, patchlevel);
- fprintf(outfile, "#\n");
-
- /* Setup a default environment to use */
- fprintf(outfile, "# Set a default pen pattern, pen width, unit and font for subsequent objects\n");
- fprintf(outfile, "<Pen 0>\n");
- fprintf(outfile, "<Fill 15>\n");
- fprintf(outfile, "<PenWidth 0.5 pt>\n");
- fprintf(outfile, "<Separation 0>\n");
- fprintf(outfile, "<Units Ucm>\n");
- fprintf(outfile, "<Font <FFamily `Times'> <FSize %d> <FPlain Yes>>\n", MIF_PSIZE);
- fprintf(outfile, "#\n");
- } /* MIF file created */
- }
-
- /* Finish of a MIF output file */
- MIF_reset()
- {
- /* Process if inside a MIF file and not inside a Frame */
- if (mif_initialized != 0 && mif_in_frame == 0) {
- /* Finish off the MIF file */
- fprintf(outfile, "#\n");
- fprintf(outfile, "# End of MIFFile\n");
-
- /* Tell this terminal driver that the output is finished */
- mif_initialized = 0;
- } /* MIF file finished */
- }
-
- /* Start plotting a Frame (-> graphics mode) */
- MIF_graphics()
- {
- int i;
-
- /* Process if not inside a Frame */
- if (mif_initialized != 0 && mif_in_frame == 0) {
- /* Tell that this terminal driver is working with a plot frame */
- mif_in_frame = 1;
-
- /* Update frame number */
- mif_frameno++;
-
- /* Set current position */
- free_mif_line();
- mif_line.fpos_x = GNP_TO_MIF(0);
- mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
-
- /* Set drawing properties */
- mif_pen[0] = '\0';
- mif_pen_width[0] = '\0';
- mif_separation[0] = '\0';
- sprintf(mif_justify, " <TLAlignment Left> ");
-
- /* Reset group ID generator */
- for (i = 0; i < MIF_NGROUP_ID; i++) {
- mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
- mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
- }
-
- /* Frame preamble */
- fprintf(outfile, "#\n");
- fprintf(outfile, "# Frame number %d with plot of graphics\n", mif_frameno);
- fprintf(outfile, "<Frame\n");
- fprintf(outfile, "\t<Pen 15>\n");
- fprintf(outfile, "\t<Fill 15>\n");
- fprintf(outfile, "\t<PenWidth 0.5 pt>\n");
- fprintf(outfile, "\t<Separation 0>\n");
- fprintf(outfile, "\t<BRect 0.000 %.3f %.3f %.3f>\n",
- ((float) mif_frameno)*GNP_TO_MIF(MIF_YMAX+100), GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
- fprintf(outfile, "\t<NSOffset 0.000>\n");
- fprintf(outfile, "\t<BLOffset 0.000>\n");
- } /* Frame created */
- }
-
- /* Stop plotting a Frame (-> text mode) */
- MIF_text()
- {
- int i;
-
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Draw pending line */
- if (mif_polyline == TRUE)
- put_mif_line();
-
- /* Group the used plot primitives */
- fprintf(outfile, "\t#\n");
- fprintf(outfile, "\t# Group the the objects in groups to make the chart easier to manipulate\n");
- fprintf(outfile, "\t# after it's imported into FrameMaker.\n");
-
- for (i = 0; i < MIF_NGROUP_ID; i++) {
- if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
- mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
- fprintf(outfile, "\t<Group\n");
- fprintf(outfile, "\t\t<ID %d>\n", mif_group_id[i].group_id);
- fprintf(outfile, "\t>\n");
- }
- }
-
- /* Frame post amble */
- fprintf(outfile, ">\n");
- fprintf(outfile, "# End of Frame number %d\n", mif_frameno);
- fprintf(outfile, "#\n");
-
- /* Tell that this terminal driver is not working with a plot frame */
- mif_in_frame = 0;
- } /* Frame finshed */
- }
-
- /* Select type of line in grapics */
- /* NOTE: actually written to output the first time a primitive is drawn AFTER this call */
- MIF_linetype(linetype)
- int linetype; /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
- {
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Draw pending line */
- if (mif_polyline == TRUE)
- put_mif_line();
-
- /* Translate gnuplot pen types to MIF pen types */
- if (linetype < 0) { /* Special lines */
- if (linetype == -1) {
- mif_pentype = 8+MIF_NPENS; /* -1 */
- if (mif_colour == TRUE)
- sprintf(mif_separation, " <Separation 0> ");
- }
- else {
- mif_pentype = 0+MIF_NPENS; /* -2 or less */
- if (mif_colour == TRUE)
- sprintf(mif_separation, " <Separation 0> ");
- }
- sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
- }
- else { /* Normal lines */
- mif_pentype = (linetype)%MIF_NPENS; /* 0-(MIF_NPENS-1) */
- sprintf(mif_pen_width, " <PenWidth 0.5 pt> ");
- if (mif_colour == TRUE)
- sprintf(mif_separation, " <Separation %d> ", 2+(mif_pentype%6)); /* 2-7 */
- }
-
- /* Set pen type */
- sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype%MIF_NPENS]);
-
- } /* Primitive processed */
- }
-
- /* Draw the text horisontally or vertically (90 degrees counterclockwise) */
- int MIF_text_angle(ang)
- int ang;
- {
- if (ang != 0)
- mif_text_ang = MIF_TEXT_VER;
- else
- mif_text_ang = MIF_TEXT_HOR;
-
- return(TRUE);
- }
-
- /* Justify following text lines (MIF_put_text()) relative to the insertion point */
- MIF_justify_text(mode)
- /* NOTE: actually written to output in text primitives which are drawn AFTER this call */
- enum JUSTIFY mode;
- {
- int rval = TRUE;
-
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
- switch (mode) {
- case LEFT:
- sprintf(mif_justify, " <TLAlignment Left> ");
- break;
- case CENTRE:
- sprintf(mif_justify, " <TLAlignment Center> ");
- break;
- case RIGHT:
- sprintf(mif_justify, " <TLAlignment Right> ");
- break;
- default:
- rval = FALSE;
- break;
- }
-
- } /* Primitive processed */
- else {
- rval = FALSE;
- }
-
- return(rval);
- }
-
- /* Draw a vector from current position to (x, y) and change current position. */
- /* NOTE: actually written to output the first time another primitive is called AFTER this call */
- MIF_vector(x, y)
- unsigned int x, y;
- {
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Setup the vector as a part of the line */
- insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST-(int)y));
-
- /* Draw pending line -> vector */
- if (mif_polyline == FALSE)
- put_mif_line();
-
- } /* Vector processed */
- }
-
- /* Move current position */
- MIF_move(x, y)
- unsigned int x, y;
- {
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Draw pending line */
- if (mif_polyline == TRUE)
- put_mif_line();
-
- mif_line.fpos_x = GNP_TO_MIF(x);
- mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST-(int)y);
- }
- }
-
- /* Draw the text string str at (x, y). Adjust according to MIF_justify_text(). Change current position. */
- MIF_put_text(x, y, str)
- unsigned int x, y;
- char str[];
- {
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Draw pending line */
- if (mif_polyline == TRUE)
- put_mif_line();
-
- /* Adjust current position for text-graphics alignment */
- MIF_move(x, y-MIF_VCHAR/5);
-
- if (strlen(str) > 0) {
-
- /* Draw the text */
- fprintf(outfile, "\t<TextLine <GroupID %d> %s %s %s\n",
- MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
- fprintf(outfile, "\t\t<TLOrigin %.3f %.3f> %s %s <String `%s'>\n",
- mif_line.fpos_x, mif_line.fpos_y, mif_justify,
- (mif_text_ang == MIF_TEXT_VER)? "<Angle 90>": "",
- str);
- fprintf(outfile, "\t>\n");
-
- /* Register the used group ID */
- proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
-
- /* Avoid to redraw this. The MIF system should remember it. */
- mif_pen[0] = '\0';
- mif_pen_width[0] = '\0';
- mif_separation[0] = '\0';
-
- mif_justify[0] = '\0'; /* Independent of linetype */
- }
- } /* Text processed */
- }
-
-
- /* Insert one point in the line */
- static int insert_mif_line(fx, fy)
- float fx, fy;
- {
- int rval = TRUE;
-
- if ((mif_line.prev->next = (struct mif_line *) alloc(sizeof(struct mif_line),"MIF driver")) != (struct mif_line *) NULL) {
- /* Link */
- mif_line.prev->next->next = &mif_line;
- mif_line.prev->next->prev = mif_line.prev;
- mif_line.prev = mif_line.prev->next;
-
- /* Fill */
- mif_line.prev->fpos_x = fx;
- mif_line.prev->fpos_y = fy;
-
- rval = TRUE;
- }
- else { /* Failed to allocate */
- /* Relink */
- mif_line.prev->next = &mif_line;
-
- rval = FALSE;
- }
-
- return(rval);
- }
-
-
- /* Register group ID. Update group ID existance. */
- /* Returns: 1 group_id belongs to a MIF group
- 0 group_id does not belong to a MIF group
- -1 not inside a Frame
- -2 group ID list is full
- */
- static int proc_group_id(group_id)
- int group_id;
- {
- int i, rval = 0;
-
- /* Process if inside a Frame */
- if (mif_initialized != 0 && mif_in_frame != 0) {
-
- /* Find out the group ID, or a free group ID slot index. */
- for (i = 0; i < MIF_NGROUP_ID &&
- mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
- mif_group_id[i].group_id != group_id;
- i++) {
- /* Don't check the group_existance variable */
- }
-
- if (i < MIF_NGROUP_ID) {
- if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
- /* Register as new group ID for eventual use as MIF group */
- mif_group_id[i].group_id = group_id;
- mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
- }
- else {
- /* If second use of this group ID -> create a new MIF group */
- if (mif_group_id[i].group_id == group_id) {
- mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
- /* NOTE: a group MUST have at least two members. */
- rval = 1;
- }
- }
- }
- else {
- rval = -2; /* No place for this group ID in the list */
- }
-
- } /* Group ID processed */
- else {
- rval = -1; /* Not inside a Frame */
- }
-
- /* Return MIF group status */
- return(rval);
- }
-
-